#ifndef _sdl_singleton_h_
#define _sdl_singleton_h_

#include "SDL.h"
#include "sdl_ptr.h"

/**
 * \brief Szablon do dziedziczenia obiektów o nie więcej niż jednej instancji
 * Niektóre obiekty mają tylko jedną instancję. Przykłady: pętla główna, ekran, menadżer wejścia.
 * Nie należy nadużywać, czasem może okazać się potrzebne posiadanie więcej instancji czegośtam.
 * Przykład:
 * @code
 * 	class moja_klasa:public sdl_singleton<moja_klasa>, public sdl_prim {};
 * 	sdl_ptr<moja_klasa> ptr = give<moja_klasa>();
 * @endcode
 * Oczywiście należy zadbać o zdefiniowanie statycznego pola __field i __mutex dla każdej klasy
 * @code
 * 	template<> sdl_ptr<moja_klasa>	sdl_singleton<moja_klasa>::__field = NULL;
 * @endcode
 */

template<class obj_t>

class sdl_singleton {
    //	template<class sdl_singleton>	friend class __sdl_singleton_cleaner;
    static sdl_ptr<obj_t> __field;
    //	static SDL_mutex * __mutex;

protected:

    /*
     * prywatny konstruktor i destruktor - niemożliwe bezpośrednie utworzenie obiektu
     */
    sdl_singleton() {
        //__mutex=SDL_CreateMutex();
    }

    virtual ~sdl_singleton() {
        //SDL_DestroyMutex(__mutex);
    }

public:
    ///zwraca jedną i jedyną instancję

    static const sdl_ptr<obj_t> & __give() {
        if (!__field) {
            //SDL_mutexP(__mutex);
            if (!__field) {
                __field = sdl_ptr<obj_t > (new obj_t);
                //__field->__add_ref();
            }

            //SDL_mutexV(__mutex);
        }

        return __field;
    }
};

///pozwala na stosowanie give<something>() zamiast something::__give()

template<class obj_t>
static const sdl_ptr<obj_t> & give() {
    if (!obj_t::__give())
        std::cerr << "give(): pusty wskaźnik" << std::endl;

    return obj_t::__give();
}

///dziedziczenie z tego szablonu zapewnia kolejność inicjalizacji

template<class prim_t>
class depends {
    sdl_ptr<prim_t> dependant_ptr;
public:

    depends() :
    dependant_ptr(give<prim_t>()) {
    }
};

#endif //_sdl_singleton_h_
